﻿#pragma once
#include "function.h"
#include "appconfig.h"

// Procedures
// Procedures
void detectionBall (HObject ho_image, HObject *ho_regionhole, HObject *ho_regionball,
    HObject *ho_regioninner, HObject *ho_regionerror, HObject *ho_regioncenter, HObject *ho_regionouter,
    HTuple hv_threshold, HTuple hv_match_radius, HTuple hv_ball_threshold, HTuple hv_inner_radius,
    HTuple hv_center_threshold, HTuple hv_center_size, HTuple hv_outer_radius, HTuple hv_error_gray_threshold,
    HTuple hv_error_size_threshold, HTuple *hv_ret, HTuple *hv_empty_list, HTuple *hv_error_list,
    HTuple *hv_twoball_list, HTuple *hv_match_radius_now)
{

  // Local iconic variables
  HObject  ho_Region, ho_RegionFillUp, ho_ConnectedRegions;
  HObject  ho_SelectedRegions1, ho_SelectedRegions, ho_ObjectSelected;
  HObject  ho_BallErosion, ho_ImageReducedHole, ho_BallRegions;
  HObject  ho_ConnectedBallRegions, ho_SelectedBallRegion;
  HObject  ho_CircleInner, ho_ImageReducedCircleInner, ho_RegionBlackCenter;
  HObject  ho_CircleOuter, ho_RegionDifference, ho_ImageRegionDifference;
  HObject  ho_ImageMean, ho_RegionDynThresh, ho_ErrorRegions;
  HObject  ho_SelectedErrorRegions, ho_connectionregionhole;

  // Local control variables
  HTuple  hv_pi, hv_Number, hv_Row1, hv_Column1;
  HTuple  hv_Radius, hv_Index, hv_AreaBall, hv_RowBall, hv_ColumnBall;
  HTuple  hv_Radiusball, hv_Area, hv_Row, hv_Column, hv_RegionBlackCenterArea;
  HTuple  hv_RegionBlackCenterRow, hv_RegionBlackCenterColumn;
  HTuple  hv_ErrorNumber, hv_center_black_radius_now;


  Threshold(ho_image, &ho_Region, 0, hv_threshold);
  FillUp(ho_Region, &ho_RegionFillUp);
  Connection(ho_RegionFillUp, &ho_ConnectedRegions);

  hv_pi = 3.1415926;
  SelectShape(ho_ConnectedRegions, &ho_SelectedRegions1, "area", "and", ((hv_pi*hv_match_radius)*hv_match_radius)*0.7,
      ((hv_pi*hv_match_radius)*hv_match_radius)*1.3);
  SelectShape(ho_SelectedRegions1, &ho_SelectedRegions, "outer_radius", "and", hv_match_radius*0.7,
      hv_match_radius*1.3);
  SortRegion(ho_SelectedRegions, &(*ho_regionhole), "character", "true", "row");

  CountObj((*ho_regionhole), &hv_Number);
  if (0 != (int(hv_Number==0)))
  {
    (*hv_ret) = -2;
    // stop(...); only in hdevelop
    return;
  }
  SmallestCircle((*ho_regionhole), &hv_Row1, &hv_Column1, &hv_Radius);
  TupleMean(hv_Radius, &(*hv_match_radius_now));



  //match_radius_now := match_radius_now + 'ball radius' + match_radius_now$'0.1f'

  GenEmptyObj(&(*ho_regionball));

  GenEmptyObj(&(*ho_regioninner));
  GenEmptyObj(&(*ho_regionouter));
  GenEmptyObj(&(*ho_regionerror));
  GenEmptyObj(&(*ho_regioncenter));

  (*hv_error_list) = HTuple();
  (*hv_empty_list) = HTuple();
  (*hv_twoball_list) = HTuple();

  {
  HTuple end_val34 = hv_Number;
  HTuple step_val34 = 1;
  for (hv_Index=1; hv_Index.Continue(end_val34, step_val34); hv_Index += step_val34)
  {
    SelectObj((*ho_regionhole), &ho_ObjectSelected, hv_Index);



    ErosionCircle(ho_ObjectSelected, &ho_BallErosion, 15);
    ReduceDomain(ho_image, ho_BallErosion, &ho_ImageReducedHole);
    Threshold(ho_ImageReducedHole, &ho_BallRegions, hv_ball_threshold, 255);
    Connection(ho_BallRegions, &ho_ConnectedBallRegions);
    SelectShapeStd(ho_ConnectedBallRegions, &ho_SelectedBallRegion, "max_area", 70);
    AreaCenter(ho_SelectedBallRegion, &hv_AreaBall, &hv_RowBall, &hv_ColumnBall);
    SmallestCircle(ho_SelectedBallRegion, &hv_RowBall, &hv_ColumnBall, &hv_Radiusball);
    if (0 != (HTuple(int(hv_Radiusball<40)).TupleOr(int(hv_AreaBall<((hv_pi*40)*40)))))
    {

      (*hv_ret) = -1;
      TupleConcat((*hv_empty_list), hv_Index, &(*hv_empty_list));
      Union2((*ho_regionerror), ho_ObjectSelected, &(*ho_regionerror));
      // stop(...); only in hdevelop
      continue;
    }
    Union2((*ho_regionball), ho_SelectedBallRegion, &(*ho_regionball));
    AreaCenter(ho_SelectedBallRegion, &hv_Area, &hv_Row, &hv_Column);
    GenCircle(&ho_CircleInner, hv_Row, hv_Column, hv_inner_radius);
	GenCircle(&ho_CircleOuter, hv_Row, hv_Column, hv_outer_radius);


	Union2((*ho_regioninner), ho_CircleInner, &(*ho_regioninner));
	Union2((*ho_regionouter), ho_CircleOuter, &(*ho_regionouter));

    ReduceDomain(ho_image, ho_CircleInner, &ho_ImageReducedCircleInner);
    Threshold(ho_ImageReducedCircleInner, &ho_RegionBlackCenter, 0, hv_center_threshold);
    AreaCenter(ho_RegionBlackCenter, &hv_RegionBlackCenterArea, &hv_RegionBlackCenterRow,
        &hv_RegionBlackCenterColumn);
    if (0 != (int(hv_RegionBlackCenterArea>hv_center_size)))
    {
      (*hv_ret) = -2;
      TupleConcat((*hv_twoball_list), hv_Index, &(*hv_twoball_list));
      Union2((*ho_regioncenter), ho_RegionBlackCenter, &(*ho_regioncenter));
      // stop(...); only in hdevelop
      continue;
    }

    
    Difference(ho_CircleOuter, ho_CircleInner, &ho_RegionDifference);

    ReduceDomain(ho_image, ho_RegionDifference, &ho_ImageRegionDifference);


    MeanImage(ho_ImageRegionDifference, &ho_ImageMean, 25, 25);
    DynThreshold(ho_ImageRegionDifference, ho_ImageMean, &ho_RegionDynThresh, hv_error_gray_threshold,
        "dark");
    Connection(ho_RegionDynThresh, &ho_ErrorRegions);


    SelectShape(ho_ErrorRegions, &ho_SelectedErrorRegions, "area", "and", hv_error_size_threshold,
        9999999);
    CountObj(ho_SelectedErrorRegions, &hv_ErrorNumber);
    if (0 != (int(hv_ErrorNumber>0)))
    {
      (*hv_ret) = 0;
      // stop(...); only in hdevelop
      TupleConcat((*hv_error_list), hv_Index, &(*hv_error_list));
      Union2((*ho_regionerror), ho_SelectedErrorRegions, &(*ho_regionerror));
      continue;
    }
  }
  }



  CountObj((*ho_regionball), &hv_Number);
  if (0 != (int(hv_Number>0)))
  {
    Connection((*ho_regionhole), &ho_connectionregionhole);
    SmallestCircle(ho_connectionregionhole, &hv_Row, &hv_Column, &hv_Radius);
    TupleMean(hv_Radius, &hv_center_black_radius_now);
  }
  if (0 != (int(((*hv_error_list).TupleLength())>0)))
  {
    (*hv_ret) = 0;
    return;
  }

  (*hv_ret) = 1;
  return;
}



Function::Function(QDialog* parent, QString path_in, QString section) : QDialog(parent)
{
    m_path_para = path_in;
    m_section = "common";




    m_qsettings = new QSettings(path_in, QSettings::IniFormat);



    QString msg;



    //m_detection_character->m_model_image_path = m_model_image_path;

    this->setWindowTitle("检测");
    QRect desktop_rect = QApplication::desktop()->geometry();
    double ratio_x = desktop_rect.width() / 1920.0;
    double ratio_y = desktop_rect.height() / 1080.0;

    move(0, 0);
    setFixedSize(1920 * ratio_x, 950 * ratio_y);


    m_listview = new QListView(this);
    m_listview->setSelectionBehavior(QAbstractItemView::SelectRows);	// 设置选择行为时每次选择一行
    m_listview->setEditTriggers(QAbstractItemView::NoEditTriggers);		// 设置不可编辑
    //m_listview->setStyleSheet("selection-background-color:lightblue;");	// 设置选中背景色
    m_listview->setGeometry(400 * ratio_x, 0, 240*ratio_x, 800 * 1.2 * ratio_y);
    m_listview_model = new QStringListModel();
    m_listview->setModel(m_listview_model);
    connect(m_listview, &QListView::clicked, this, &Function::listViewClick);

    m_view = new QtQGraphicsView(this);
    m_view->setGeometry(660 * ratio_x, 0, 950 * 1.25 * ratio_x, 780 * 1.25 * ratio_y);

    QSize control_size(180 * ratio_x, 25 * ratio_y);

    QWidget* p = new QWidget(this);
    p->move(0 * ratio_x, 0 * ratio_y);
    p->setFixedSize(400 * ratio_x, 950 * ratio_y);

    QGridLayout* qgridLayout = new QGridLayout();
    p->setLayout(qgridLayout);

    int index = 0;

    m_showqlabel = new ShowQLabel(this);
    m_showqlabel->setFixedSize(225, 50);
    qgridLayout->addWidget(m_showqlabel, index, 0);

    index++;
    m_qcombobox_unuse_use = new QComboBox(this);
    m_qcombobox_unuse_use->setFixedSize(control_size);
    m_qcombobox_unuse_use->addItem("不启动检测");
    m_qcombobox_unuse_use->addItem("启动检测");
    qgridLayout->addWidget(m_qcombobox_unuse_use, index, 0);

    index++;
    QSize ButtonSize(150 * ratio_x, 40 * ratio_y);
    m_pushbutton_load_image = new QPushButton(this);
    m_pushbutton_load_image->setText("载入单张图像");
    m_pushbutton_load_image->setFixedSize(ButtonSize);
    connect(m_pushbutton_load_image, &QPushButton::clicked, this, [=]() {
        QString filename;
        filename = QFileDialog::getOpenFileName(this,
            tr("选择图像"),
            "",
            tr("Images (*.png *.bmp *.jpg)"));
        if (filename.isEmpty())
        {
            return;
        }

        m_image = imread(filename.toLocal8Bit().toStdString(), IMREAD_UNCHANGED);



        if (m_image.empty())
        {
//            //QMessageBox::information(nullptr, "", "加载检测图像错误");
            return;
        }

        QImage q_image = matToQImage(m_image);
        m_view->setImage(q_image, "",Qt::green);
        });
    qgridLayout->addWidget(m_pushbutton_load_image, index, 0);

    m_pushbutton_load_dir = new QPushButton(this);
    m_pushbutton_load_dir->setText("载入图像目录");
    m_pushbutton_load_dir->setFixedSize(ButtonSize);
    connect(m_pushbutton_load_dir, &QPushButton::clicked, this, [=]() {
        QString directory;

        directory = QFileDialog::getExistingDirectory(this,
            tr("选择文件夹"),
            "");
        if (directory.isEmpty())
        {
            return;
        }

        QDir dir(directory);
        dir.setFilter(QDir::Files | QDir::NoSymLinks);
        QStringList filters;
        filters << "*.bmp" << "*.jpg" << "*.png";
        dir.setNameFilters(filters);



        QStringList  string_list = dir.entryList();
        QStringList string_list_path;
        foreach(QString  var, string_list) {
            string_list_path << directory + "/" + var;
        }

        m_listview_model->setStringList(string_list_path);
        });
    qgridLayout->addWidget(m_pushbutton_load_dir, index, 1);

    index++;
    m_qlabel_times = new QLabel();
    m_qlabel_times->setText("采集次数");
    m_qlabel_times->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_times, index, 0);
    m_qspinbox_times = new QLabel();
    m_qspinbox_times->setFixedSize(control_size);
    
    qgridLayout->addWidget(m_qspinbox_times, index, 1);

    index++;
	m_qlabel_number_rows = new QLabel(this);
	m_qlabel_number_rows->setFixedSize(control_size);
	qgridLayout->addWidget(m_qlabel_number_rows, index, 0);

	m_qlabel_ball_number = new QLabel();
	m_qlabel_ball_number->setFixedSize(control_size);
	qgridLayout->addWidget(m_qlabel_ball_number, index, 1);

    index++;
    m_qlabel_threshold_hole = new QLabel();
    m_qlabel_threshold_hole->setText("黑孔灰度阈值最小值");
    m_qlabel_threshold_hole->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_threshold_hole,index,0);

    index++;
    m_qspinbox_threshold_hole = new QSpinBox();
    m_qspinbox_threshold_hole->setFixedSize(control_size);
    m_qspinbox_threshold_hole->setMinimum(0);
    m_qspinbox_threshold_hole->setMaximum(255);
    qgridLayout->addWidget(m_qspinbox_threshold_hole,index,0);

    m_qslider_threshold_hole = new QSlider(Qt::Horizontal);
    m_qslider_threshold_hole->setTickPosition(QSlider::NoTicks);
    m_qslider_threshold_hole->setSingleStep(1);
    m_qslider_threshold_hole->setMinimum(0);
    m_qslider_threshold_hole->setMaximum(255);

    qgridLayout->addWidget(m_qslider_threshold_hole,index,1);

    QObject::connect(m_qspinbox_threshold_hole, QOverload<int>::of(&QSpinBox::valueChanged),
                         m_qslider_threshold_hole, &QSlider::setValue);
    QObject::connect(m_qslider_threshold_hole, &QSlider::valueChanged,
                         m_qspinbox_threshold_hole, &QSpinBox::setValue);


    index++;
    m_qlabel_match_radius = new QLabel();
    m_qlabel_match_radius->setText("匹配半径");
    m_qlabel_match_radius->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_match_radius,index,0);

    index++;
    m_qspinbox_match_radius = new QSpinBox();
    m_qspinbox_match_radius->setFixedSize(control_size);
    m_qspinbox_match_radius->setMinimum(0);
    m_qspinbox_match_radius->setMaximum(200);
    qgridLayout->addWidget(m_qspinbox_match_radius, index, 0);

    m_qslider_match_radius = new QSlider(Qt::Horizontal);
    m_qslider_match_radius->setTickPosition(QSlider::NoTicks);
    m_qslider_match_radius->setSingleStep(1);
    m_qslider_match_radius->setMinimum(0);
    m_qslider_match_radius->setMaximum(200);
    qgridLayout->addWidget(m_qslider_match_radius,index,1);

    QObject::connect(m_qspinbox_match_radius, QOverload<int>::of(&QSpinBox::valueChanged),
                         m_qslider_match_radius, &QSlider::setValue);
    QObject::connect(m_qslider_match_radius, &QSlider::valueChanged,
                         m_qspinbox_match_radius, &QSpinBox::setValue);

    index++;
	m_qlabel_ball_threshold = new QLabel();
	m_qlabel_ball_threshold->setText("钢球灰度阈值最小值");
	m_qlabel_ball_threshold->setFixedSize(control_size);
	qgridLayout->addWidget(m_qlabel_ball_threshold, index, 0);
	index++;

	m_qspinbox_ball_threshold = new QSpinBox();
	m_qspinbox_ball_threshold->setFixedSize(control_size);
    m_qspinbox_ball_threshold->setMinimum(10);
	m_qspinbox_ball_threshold->setMaximum(255);
	qgridLayout->addWidget(m_qspinbox_ball_threshold, index, 0);

	m_qslider_ball_threshold = new QSlider(Qt::Horizontal);
	m_qslider_ball_threshold->setTickPosition(QSlider::NoTicks);
	m_qslider_ball_threshold->setSingleStep(1);
    m_qslider_ball_threshold->setMinimum(10);
	m_qslider_ball_threshold->setMaximum(255);
	qgridLayout->addWidget(m_qslider_ball_threshold, index, 1);
    QObject::connect(m_qspinbox_ball_threshold, QOverload<int>::of(&QSpinBox::valueChanged),
                         m_qslider_ball_threshold, &QSlider::setValue);
    QObject::connect(m_qslider_ball_threshold, &QSlider::valueChanged,
                         m_qspinbox_ball_threshold, &QSpinBox::setValue);


    index++;
    m_qlabel_inner_radius = new QLabel();
    m_qlabel_inner_radius->setText("球内径");
    m_qlabel_inner_radius->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_inner_radius,index,0);
    m_qspinbox_inner_radius = new QSpinBox();
    m_qspinbox_inner_radius->setFixedSize(control_size);
    m_qspinbox_inner_radius->setMinimum(0);
    qgridLayout->addWidget(m_qspinbox_inner_radius, index, 1);

    index++;
    m_qlabel_center_threshold = new QLabel();
    m_qlabel_center_threshold->setText("球心黑斑阈值");
    m_qlabel_center_threshold->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_center_threshold,index,0);
    m_qspinbox_center_threshold = new QSpinBox();
    m_qspinbox_center_threshold->setFixedSize(control_size);
    m_qspinbox_center_threshold->setMinimum(0);
    m_qspinbox_center_threshold->setMaximum(255);
    qgridLayout->addWidget(m_qspinbox_center_threshold, index, 1);

    index++;
    m_qlabel_center_size = new QLabel();
    m_qlabel_center_size->setText("球心黑斑最小面积");
    m_qlabel_center_size->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_center_size,index,0);
    m_qspinbox_center_size = new QSpinBox();
    m_qspinbox_center_size->setFixedSize(control_size);
    m_qspinbox_center_size->setMinimum(0);
    m_qspinbox_center_size->setMaximum(10000);
    qgridLayout->addWidget(m_qspinbox_center_size, index, 1);

    index++;
    m_qlabel_outer_radius = new QLabel();
    m_qlabel_outer_radius->setText("球外径");
    m_qlabel_outer_radius->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_outer_radius,index,0);
    m_qspinbox_outer_radius = new QSpinBox();
    m_qspinbox_outer_radius->setFixedSize(control_size);
    m_qspinbox_outer_radius->setMinimum(0);
    m_qspinbox_outer_radius->setMaximum(1000);
    qgridLayout->addWidget(m_qspinbox_outer_radius, index, 1);


    index++;
    m_qlabel_error_gray = new QLabel();
    m_qlabel_error_gray->setText("缺陷灰度差值");
    m_qlabel_error_gray->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_error_gray,index,0);

    index++;
    m_qspinbox_error_gray = new QSpinBox();
    m_qspinbox_error_gray->setFixedSize(control_size);
    m_qspinbox_error_gray->setMinimum(0);
    m_qspinbox_error_gray->setMaximum(200);
    qgridLayout->addWidget(m_qspinbox_error_gray, index, 0);


    m_qslider_error_gray = new QSlider(Qt::Horizontal);
    m_qslider_error_gray->setTickPosition(QSlider::NoTicks);
    m_qslider_error_gray->setSingleStep(1);
    m_qslider_error_gray->setMinimum(0);
    m_qslider_error_gray->setMaximum(200);
    qgridLayout->addWidget(m_qslider_error_gray, index, 1);

    QObject::connect(m_qspinbox_error_gray, QOverload<int>::of(&QSpinBox::valueChanged),
                         m_qslider_error_gray, &QSlider::setValue);
    QObject::connect(m_qslider_error_gray, &QSlider::valueChanged,
                         m_qspinbox_error_gray, &QSpinBox::setValue);


    index++;
    m_qlabel_error_size = new QLabel();
    m_qlabel_error_size->setText("缺陷面积阈值");
    m_qlabel_error_size->setFixedSize(control_size);
    qgridLayout->addWidget(m_qlabel_error_size,index,0);

    index++;
    m_qspinbox_error_size = new QSpinBox();
    m_qspinbox_error_size->setFixedSize(control_size);
    m_qspinbox_error_size->setMinimum(0);
    m_qspinbox_error_size->setMaximum(300);
    qgridLayout->addWidget(m_qspinbox_error_size, index, 0);

    m_qslider_error_size = new QSlider(Qt::Horizontal);
    m_qslider_error_size->setTickPosition(QSlider::NoTicks);
    m_qslider_error_size->setSingleStep(1);
    m_qslider_error_size->setMinimum(0);
    m_qslider_error_size->setMaximum(300);
    qgridLayout->addWidget(m_qslider_error_size, index, 1);

    QObject::connect(m_qspinbox_error_size, QOverload<int>::of(&QSpinBox::valueChanged),
                         m_qslider_error_size, &QSlider::setValue);
    QObject::connect(m_qslider_error_size, &QSlider::valueChanged,
                         m_qspinbox_error_size, &QSpinBox::setValue);

    index++;
    m_qcombobox_save_wrong = new QComboBox(this);
    m_qcombobox_save_wrong->setFixedSize(control_size);
    m_qcombobox_save_wrong->addItem("不存错误图像");
    m_qcombobox_save_wrong->addItem("存错误图像");
    qgridLayout->addWidget(m_qcombobox_save_wrong, index, 0);

    m_qcombobox_save_right = new QComboBox(this);
    m_qcombobox_save_right->setFixedSize(control_size);
    m_qcombobox_save_right->addItem("不存正确图像");
    m_qcombobox_save_right->addItem("存正确图像");
    qgridLayout->addWidget(m_qcombobox_save_right, index, 1);



    index++;
	m_pushbutton_show_orign_image = new QPushButton(this);
	m_pushbutton_show_orign_image->setFixedSize(control_size);
    m_pushbutton_show_orign_image->setText("显示原图");
	connect(m_pushbutton_show_orign_image, &QPushButton::clicked, this, [=]() {
		QImage q_image = matToQImage(m_image);
        m_view->setImage(q_image, "",Qt::green);
		return true;
	});
	qgridLayout->addWidget(m_pushbutton_show_orign_image, index, 0);

    m_pushbutton_detection = new QPushButton(this);
    m_pushbutton_detection->setFixedSize(control_size);
    m_pushbutton_detection->setText("检测");
    connect(m_pushbutton_detection, &QPushButton::clicked, this, &Function::detectionImage);
    qgridLayout->addWidget(m_pushbutton_detection, index, 1);

    index++;
    m_pushbutton_save_parameter = new QPushButton(this);
    m_pushbutton_save_parameter->setFixedSize(control_size);
    m_pushbutton_save_parameter->setText("保存参数");
    connect(m_pushbutton_save_parameter, &QPushButton::clicked, this, &Function::saveParameter);
    qgridLayout->addWidget(m_pushbutton_save_parameter, index, 0);

    m_pushbutton_return = new QPushButton(this);
    m_pushbutton_return->setFixedSize(control_size);
    m_pushbutton_return->setText("退出");
    qgridLayout->addWidget(m_pushbutton_return, index, 1);


    loadParameter(m_path_para, m_section);



    connect(m_qslider_threshold_hole, &QSlider::valueChanged, this, [=](int value) {
            if (m_image.empty())
            {
                return;
            }
            QString message;
            if (m_unuse_use_function == 1)
            {
                HObject image = matToHImage(m_image);
                bool state = detection(image, message);

            }

			m_image_show = m_image.clone();
			cvtColor(m_image_show, m_image_show, COLOR_GRAY2BGR);
            m_image_show = drawRegionFill(m_image_show, m_regionhole, Scalar(0, 255, 0));


            QImage q_image = matToQImage(m_image_show);
            m_view->setImage(q_image, message,Qt::green);
    });

    connect(m_qslider_match_radius, &QSlider::valueChanged, this, [=](int value) {
            m_qspinbox_match_radius->setValue(value);
            QString message;
            if (m_image.empty())
            {
                return;
            }
            if (m_unuse_use_function == 1)
            {
                HObject image = matToHImage(m_image);
                bool state = detection(image, message);

            }




			m_image_show = m_image.clone();
			cvtColor(m_image_show, m_image_show, COLOR_GRAY2BGR);
            m_image_show = drawRegionFill(m_image_show, m_regionhole, Scalar(0, 255, 0));


            QImage q_image = matToQImage(m_image_show);
            m_view->setImage(q_image, message,Qt::green);


    });

	connect(m_qslider_ball_threshold, &QSlider::valueChanged, this, [=](int value) {
		QString message;
		if (m_image.empty())
		{
			return;
		}
		if (m_unuse_use_function == 1)
		{
			HObject image = matToHImage(m_image);
			bool state = detection(image, message);
		}

		m_image_show = m_image.clone();
		cvtColor(m_image_show, m_image_show, COLOR_GRAY2BGR);
		m_image_show = drawRegion(m_image_show, m_regionball, Scalar(0, 255, 0));

		//HTuple hv_n;
		//HObject empty;
		//GenEmptyObj(&empty);
		//TestEqualObj(m_regioncenterblack, empty, &hv_n);
		//if (hv_n == 1) //两个Obj相等
		//{
		//	QImage q_image = matToQImage(m_image_show);
		//	m_view->setImage(q_image, message);
		//	return;
		//}
		//HObject HObjectConnect;
		//HTuple hv_Row, hv_Column;
		//HTuple  hv_Radius, center_black_radius_now;
		//Connection(m_regioncenterblack, &HObjectConnect);
		//SmallestCircle(HObjectConnect, &hv_Row, &hv_Column, &hv_Radius);
		//TupleMean(hv_Radius, &center_black_radius_now);

		//double center_black_radius = center_black_radius_now[0].D();
		//message += "圆心黑点半径" + QString::number(center_black_radius);

		QImage q_image = matToQImage(m_image_show);
        m_view->setImage(q_image, message,Qt::green);

	});

    connect(m_qslider_error_gray, &QSlider::valueChanged, this, [=](int value) {
            if (m_image.empty())
            {
                return;
            }
            QString message;
            if (m_unuse_use_function == 1)
            {
                HObject image = matToHImage(m_image);
                bool state = detection(image, message);

            }

            m_image_show = m_image.clone();
            cvtColor(m_image_show, m_image_show, COLOR_GRAY2BGR);
            m_image_show = drawRegionFill(m_image_show, m_error_region, Scalar(0, 0,255));



            QImage q_image = matToQImage(m_image_show);
            m_view->setImage(q_image, message,Qt::green);


    });

    connect(m_qslider_error_size, &QSlider::valueChanged, this, [=](int value) {
            if (m_image.empty())
            {
                return;
            }
            QString message;
            if (m_unuse_use_function == 1)
            {
                HObject image = matToHImage(m_image);
                bool state = detection(image, message);

            }

            m_image_show = m_image.clone();
            cvtColor(m_image_show, m_image_show, COLOR_GRAY2BGR);
            m_image_show = drawRegionFill(m_image_show, m_error_region, Scalar(0, 0,255));



            QImage q_image = matToQImage(m_image_show);
            m_view->setImage(q_image, message,Qt::green);


    });
    QImage q_image = matToQImage(m_image);
    m_view->setImage(q_image, "",Qt::green);
}

bool Function::detection(HObject image_in, QString& message)
{
    m_vector_result.assign(m_number_rows * m_ball_number, 1);
    if (m_unuse_use_function == 0)
    {
        message += "没有开启检测";
        return true;
    }

    if (!image_in.IsInitialized())
    {
        QMessageBox::critical(nullptr, m_section, "图像为空或者格式不对");
        return false;
    }
    HTuple hv_n;
    HObject empty;
    GenEmptyObj(&empty);
    TestEqualObj(image_in, empty, &hv_n);
    if (hv_n == 1) //两个Obj相等
    {
        QMessageBox::critical(nullptr, m_section, "图像为空或者格式不对");
        return false;
    }
	HTuple hv_ret;
    HTuple hv_empty_list, hv_error_list,hv_twoball_list, match_radius_now;
	try
	{
		
        detectionBall(image_in,&m_regionhole, &m_regionball, &m_regioninner,&m_error_region,&m_regioncenter,&m_regionouter,
            m_qspinbox_threshold_hole->value(), m_qspinbox_match_radius->value(),m_qspinbox_ball_threshold ->value(), m_qspinbox_inner_radius->value(),m_qspinbox_center_threshold->value(),m_qspinbox_center_size->value(), m_qspinbox_outer_radius->value() ,m_qspinbox_error_gray->value(), m_qspinbox_error_size->value(),
            &hv_ret,&hv_empty_list,&hv_error_list,&hv_twoball_list,&match_radius_now);

		HTuple hv_number;
		CountObj(m_regionhole, &hv_number);
		int number = hv_number[0].I();
        int result = hv_ret[0].I();

		if (number != m_number_rows*m_ball_number)
		{
			m_vector_result.assign(m_number_rows*m_ball_number, 0);
            message+="黑孔检测数目不对";
			result = -2;
		}


		// 使用索引访问遍历 HTuple

        for (int i = 0; i < hv_empty_list.Length(); ++i) {
            int index = hv_empty_list[i].I() - 1;
            if (index < m_vector_result.size())
            {
                m_vector_result[index] = 0;
            }
        }

		for (int i = 0; i < hv_error_list.Length(); ++i) {
			int index = hv_error_list[i].I() - 1;
			if (index < m_vector_result.size())
			{
                m_vector_result[index] = -1;
			}
		}




        for (int i = 0; i < hv_twoball_list.Length(); ++i) {
            int index = hv_twoball_list[i].I() - 1;
            if (index < m_vector_result.size())
            {
                m_vector_result[index] = -2;
            }
        }


		if (result > -2)
		{
			m_match_radius_now = match_radius_now[0].D();
            message += "黑孔半径" + QString::number(m_match_radius_now);
		}
		if (result > 0)
		{
			return true;

		}
		else
		{
			return false;
		}
	}
	catch (HException &HDevExpDefaultException)
	{
		message = HDevExpDefaultException.ErrorMessage();
		for (int i = 0; i < hv_error_list.Length(); ++i) {
			int index = hv_error_list[i].I() - 1;
			if (index < m_vector_result.size())
			{
				m_vector_result[index] = 0;
			}
		}
		return false;
	}

    
    return true;
}

void Function::detectionImage()
{
    if (m_image.empty())
    {
        //QMessageBox::information(nullptr, "", "没有图像");
        return;
    }

    int64 t1 = cv::getTickCount();

    QString message;
	bool state;
    if (m_unuse_use_function == 1)
    {
        HObject image = matToHImage(m_image);
        

        state = detection(image, message);
		if (state)
		{
			message += "OK";;
		}
		else
		{
			message += "NG";;
		}

        Mat image_out;
        createShowImage(m_ball_number, m_number_rows, m_vector_result, image_out);
        QImage Qtempimage = matToQImage(image_out);
        m_showqlabel->loadtextimage(Qtempimage, "", QColor(0, 255, 0));

        for(int i=0;i<m_vector_result.size();i++)
        {
            if(m_vector_result[i]<=0)
            {
				int row_index = i / m_ball_number;
				int column_index = i % m_ball_number;
				if (row_index ==0)
				{
					message += " 第0排";
				}
				else
				{
					message += " 第1排";
				}
                if (m_vector_result[i] ==0)
                {
                    message += "错误";
                }
                if(m_vector_result[i]==-1)
                {
                    message += "空料";
                }
                message += "" + QString::number(column_index);
            }
        }



    }
    int64 t2 = cv::getTickCount();

    double m_time_use = (t2 - t1) * 1000 / getTickFrequency();
    message += "检测时间：" + QString::number(m_time_use);

    Mat image_show;
    draw(m_image,image_show);

    QImage q_image = matToQImage(image_show);
	if (state)
	{
		m_view->setImage(q_image, message, Qt::green);
	}
	else
	{
		m_view->setImage(q_image, message, Qt::red);
	}
    
}

void Function::draw(Mat image_in, Mat& image_out)
{
    if (m_unuse_use_function)
    {
        image_out = image_in;

        if(image_in.empty())
            return;
        if(image_in.channels()==1)
        {
            cvtColor(image_in,image_in,COLOR_GRAY2BGR);
        }


        image_out = drawRegion(image_in, m_regionhole, Scalar(0, 255, 0));

        image_out = drawRegion(image_out, m_regioninner, Scalar(0, 255, 0));
        image_out = drawRegion(image_out, m_regionouter, Scalar(0, 255, 0));

		image_out = drawRegion(image_out, m_error_region, Scalar(0, 0, 255));

        image_out = drawRegion(image_out, m_regioncenter, Scalar(0, 153, 255));

		GenEmptyRegion(&m_regionhole);

		GenEmptyRegion(&m_regioninner);
		GenEmptyRegion(&m_regionouter);
        GenEmptyRegion(&m_error_region);
        GenEmptyRegion(&m_regioncenter);

    }
    else
    {
        image_out = image_in;
    }
}

void Function::listViewClick(const QModelIndex& model_index)
{
    QString image_path = model_index.data().toString();

    m_image = imread(image_path.toLocal8Bit().toStdString(), IMREAD_UNCHANGED);

    if (m_image.empty())
    {
        //QMessageBox::information(nullptr, "", "加载检测图像错误");
        return;
    }

    QImage q_image = matToQImage(m_image);
    m_view->setImage(q_image, "",Qt::green);
}

void Function::loadParameter(QString path_in, QString section)
{
    m_path_para = path_in;
    m_section = section;
    try
    {
        m_model_image_path = path_in.left(path_in.length()-4)  + ".png";
        m_image = imread(m_model_image_path.toLocal8Bit().toStdString(), IMREAD_UNCHANGED);


        QString m_exe_directory = QCoreApplication::applicationDirPath();
        QString m_para_dir = m_exe_directory + "/para";
        QString path;
        path=   m_para_dir + "/para.ini";
        //创建配置文件操作对象
        QSettings* m_settings_para = new QSettings(path, QSettings::IniFormat);
        m_ball_number =  m_settings_para->value("plc/value_ball_number", 1).toInt();
		if (m_ball_number<=0)
		{
			QMessageBox::warning(nullptr, "", "参数文件错误，每排球个数需要大于0");
			m_ball_number = 1;
		}
		m_qlabel_ball_number->setText("每排球个数"+ QString::number(m_ball_number));

        m_number_rows =  m_settings_para->value("plc/value_ball_row").toInt();
		if (m_number_rows <= 0)
		{
			QMessageBox::warning(nullptr, "", "参数文件错误，排球需要大于0");
			m_number_rows = 1;
		}
		m_qlabel_number_rows->setText(QString::number(m_number_rows) + "排");


		m_times = m_settings_para->value("plc/value_ball_times", 4).toInt();
		


        m_qspinbox_threshold_hole->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_threshold_hole",100).toInt());
        m_qspinbox_times->setText(QString::number(m_times));
        m_qspinbox_match_radius->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_match_radius",1).toInt());

        m_qspinbox_ball_threshold->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_ball_threshold", 1).toInt());
        m_qspinbox_inner_radius->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_inner_radius",1).toInt());
        m_qspinbox_center_threshold->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_center_threshold",1).toInt());
        m_qspinbox_center_size->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_center_size",1).toInt());
        m_qspinbox_outer_radius->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_outer_radius",1).toInt());
        m_qspinbox_error_gray->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_error_gray",1).toInt());
        m_qspinbox_error_size->setValue(m_qsettings->value(m_section + "/" + "m_qspinbox_error_size",1).toInt());



        m_unuse_use_function = m_qsettings->value(section + "/" + "m_unuse_use_function").toInt();
        m_save_wrong = m_qsettings->value(section + "/" + "m_save_wrong").toInt();
        m_save_right = m_qsettings->value(section + "/" + "m_save_right").toInt();
		
        m_qcombobox_unuse_use->setCurrentIndex(m_unuse_use_function);
        m_qcombobox_save_wrong->setCurrentIndex(m_save_wrong);
        m_qcombobox_save_right->setCurrentIndex(m_save_right);




    }
    catch (exception& error)
    {
        QMessageBox::critical(nullptr, error.what(), m_section + "参数需要重新设置");
    }

    return;
}

void Function::saveParameter()
{
    try
    {

        m_model_image_path = m_path_para.left(m_path_para.length()-4)  + ".png";
        if(!m_image.empty())
            imwrite(m_model_image_path.toLocal8Bit().toStdString(),m_image);

		//m_times = m_qspinbox_times->value();
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_threshold_hole", m_qspinbox_threshold_hole->value());
        //m_qsettings->setValue(m_section + "/" + "m_times", m_times);
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_match_radius", m_qspinbox_match_radius->value());

        m_qsettings->setValue(m_section + "/" + "m_qspinbox_ball_threshold", m_qspinbox_ball_threshold->value());
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_inner_radius", m_qspinbox_inner_radius->value());
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_center_threshold", m_qspinbox_center_threshold->value());
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_center_size", m_qspinbox_center_size->value());
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_outer_radius", m_qspinbox_outer_radius->value());
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_error_gray", m_qspinbox_error_gray->value());
        m_qsettings->setValue(m_section + "/" + "m_qspinbox_error_size", m_qspinbox_error_size->value());


        m_unuse_use_function = m_qcombobox_unuse_use->currentIndex();
        m_save_wrong = m_qcombobox_save_wrong->currentIndex();
        m_save_right = m_qcombobox_save_right->currentIndex();

		m_qsettings->setValue(m_section + "/" + "m_unuse_use_function", m_unuse_use_function);
        m_qsettings->setValue(m_section + "/" + "m_save_wrong", m_save_wrong);
        m_qsettings->setValue(m_section + "/" + "m_save_right", m_save_right);


    }
    catch (exception& error)
    {
        QMessageBox::critical(nullptr, error.what(), m_section + "参数需要重新设置");
    }
}


#pragma execution_character_set("utf-8")
